<?php
namespace addons\xilujob\controller;

use app\common\library\xilujob\Geohash;
//use app\common\library\xilujob\Notification;
use app\common\library\xilujob\TencentMap;
use app\common\model\xilujob\Area;
use app\common\model\xilujob\EnterpriseInfo;
use app\common\model\xilujob\JobInterview;
use app\common\model\xilujob\JobLocation;
use think\Controller;
use think\Db;
use think\db\Query;
use think\Log;
use function fast\array_get;

class Timer extends \think\addons\Controller {

    public function _initialize()
    {
        parent::_initialize();

        if (!$this->request->isCli()) {
            $this->error('只允许在终端进行操作!');
        }
    }

    /**
     * 解析地址到gps，并更新到redis
     */
    public function update_geo() {
        /**
         * @param Object $query
         * @param string $addressFieldName
         * @param bool $updateAreaIds 是否更新city_id district_id
         * @param string $cityFieldName city id的字段名, 留空认为没有city id, 用于辅助address解析
         */
        function process(Query $query, $addressFieldName, $updateAreaIds=false, $cityFieldName=null, $chunkId='id') {

            try {
                $tableName = $query->getTable();
                $map = TencentMap::default();
                $class = get_class($query->getModel());
                $query->chunk(50, function ($rows) use ($class,$addressFieldName,$tableName,$map,$updateAreaIds, $cityFieldName) {
                    $geohashTool = new Geohash();
                    $rows = collection($rows)->toArray();
                    foreach ($rows as $row) {
                        try {
                            $id = array_get($row, 'id');
                            $address = array_get($row, $addressFieldName);

                            if(!$address) {
                                Db::table($tableName)->where('id', $id)->update(['geo_status' => $class::GEO_STATUS_FAILED]);
                                continue;
                            }

                            if($cityFieldName && strpos($address,'市')===false) {
                                $city = Area::field('id,name')->cache(true,3600)->find($row[$cityFieldName]);
                                if($city) {
                                    $address = $city['name'].' '.$address;
                                }
                            }
                            $res = $map->convertAddressToGeo($address);
                            if(array_get($res,'status')===null) {
                                //无响应 下一次再试
                                continue;
                            }
                            if(array_get($res,'status')!==0) {
                                if(array_get($res,'status')==120) {
//                                    Log::debug('下次再试'.json_encode($res, JSON_UNESCAPED_UNICODE));
                                    continue;
                                }
                                //解析失败 改状态为失败
                                Db::table($tableName)->where('id', $id)->update(['geo_status' => $class::GEO_STATUS_FAILED]);
//                                Log::error('地址解析异常:'.$tableName." #".Arr::get($row,'id'));
                                Log::error(sprintf('地址解析异常: %s #%s %s', $tableName, array_get($row,'id'), $address));
                                Log::error(json_encode($res, JSON_UNESCAPED_UNICODE));
                                continue;
                            }
                            $lng = array_get($res, 'result.location.lng');
                            $lat = array_get($res, 'result.location.lat');
                            $reliability = array_get($res, 'result.reliability');
                            $city = array_get($res, 'result.address_components.city');
                            $district = array_get($res, 'result.address_components.district');
//                            Log::debug($address.':reliability '.$reliability." $lng $lat $city $district. ".json_encode($res,JSON_UNESCAPED_UNICODE));

                            $geohash = $geohashTool->encode($lat, $lng, 8);
                            $updateData = ['geo_status'=>$class::GEO_STATUS_PARSED, 'lng' => $lng, 'lat' => $lat, 'geohash'=>$geohash];
                            if($updateAreaIds) {
                                $cityId = Area::where('name',$city)->value('id');
                                $districtId = Area::where('name', $district)->value('id');
                                $updateData['city_id'] = $cityId ? : 0;
                                $updateData['district_id'] = $districtId ? : 0;
                            }
                            Db::table($tableName)->where('id',$id)->update($updateData);
                            sleep(1);//等待一秒， 以免触发每秒请求数限制
                        }catch (\Exception $e) {
                            Log::error('地址解析异常:'.$tableName." #".array_get($row,'id'));
                            Log::error('Line '.$e->getLine());
                            Log::error($e->getMessage()."\n".$e->getTraceAsString());
                        }
                    }
                }, $chunkId);
            }catch (\Exception $e) {
                Log::error('地址解析查询异常:'.$query->getTable());
                Log::error($e->getMessage()."\n".$e->getTraceAsString());
            }
        }
        Db::startTrans();
        //更新课程地址
        $jobLocations = (new JobLocation())->where('geo_status', EnterpriseInfo::GEO_STATUS_PARSING)->field('id,city_id,address');
        $enterpriseInfoList = (new EnterpriseInfo())->where('geo_status', EnterpriseInfo::GEO_STATUS_PARSING)->field('id,city_id,address');

        process($jobLocations, 'address', false, 'city_id');
        process($enterpriseInfoList, 'address', true, 'city_id', 'id');
        Db::commit();
    }

    /**
     * 提醒面试， 2小时前， 发短信
     */
    public function interview_notify() {
        JobInterview::where('send_status',0)
            ->where('interview_time','<', time()+7200)
            ->where('status',JobInterview::STATUS_INTERVIEW_ACCEPTED)
            ->chunk(20,function ($list) {
                foreach($list as $interview) {
                    try {
                        $interview->save(['send_status'=>1]);
                    }catch (\Exception $e) {
                        Log::error($e->getMessage()."\n".$e->getTraceAsString());
                    }
                }
            });
    }

}